﻿using System;
using System.IO;

namespace Tzx.TUpdater.Utilities
{
    /// <summary>
    /// 以文本文件简单记录日志(2013-9-3)
    /// </summary>
    public class LogFile
    {
        /// <summary>
        /// 指定的文件名
        /// </summary>
        private static bool isNamedLogFile = false;

        #region 单例(懒汉模式)

        /***
         * 单例模式的正规写法,参考: http://blog.sina.com.cn/s/blog_4b8589b70100c5mt.html
         **/

        /// <summary>
        /// 静态单例
        /// </summary>
        private volatile static LogFile _instance = null;

        /// <summary>
        /// 线程加锁对象
        /// </summary>
        private static readonly object ObjLockHelper = new object();

        /// <summary>
        /// 阻止被外部实例化
        /// </summary>
        private LogFile() { }

        /// <summary>
        /// 单例初始化(线程加锁)
        /// </summary>
        private static void LockInitInstance()
        {
            //使用后期绑定,在应用程序还未使用此类前,不实例化,以节省资源
            if (_instance == null)
            {
                lock (ObjLockHelper) //使用lock关键字进行线程的加锁
                {
                    if (_instance == null)
                    {
                        _instance = new LogFile();
                    }
                }
            }
        }

        /// <summary>
        /// 获得单例(使用默认存储目录和文件名)
        /// </summary>
        public static LogFile Instance()
        {
            LockInitInstance();
            return _instance;
        }
        /// <summary>
        /// 获得单例(使用默认存储目录和文件名)
        /// </summary>
        public static LogFile Me
        {
            get
            {
                LockInitInstance();
                return _instance;
            }
        }

        /// <summary>
        /// 获得单例(指定存储目录)
        /// </summary>
        /// <param name="fileFolder">保存目录,若不指定目录则保存在"C:\Logs\"下</param>
        public static LogFile Instance(string fileFolder)
        {
            LockInitInstance();

            _instance.FileFolder = fileFolder;
            //isNamedLogDirectory = true;

            return _instance;
        }

        /// <summary>
        /// 获得单例(指定存储目录和文件名)
        /// </summary>
        /// <param name="fileFolder">保存目录,若不指定目录则保存在"C:\Logs\"下</param>
        /// <param name="fileName">文件名,若不指定,则以当天日期为文件名</param>
        public static LogFile Instance(string fileFolder, string fileName)
        {
            LockInitInstance();

            _instance.FileFolder = fileFolder;
            _instance.FileName = fileName;
            //isNamedLogDirectory = true;
            isNamedLogFile = true;

            return _instance;
        }
        #endregion

        /// <summary>
        /// 记录异常信息
        /// </summary>
        public void LogException(Exception ex)
        {
            WriteLog("异常", new string[] { (ex.GetType()).FullName, ex.Message, ex.StackTrace });

            if (ex.InnerException != null)
            {
                WriteLog("异常",
                         new string[]
                             {
                                 (ex.InnerException.GetType()).FullName, ex.InnerException.Message,
                                 ex.InnerException.StackTrace
                             });
            }
        }

        /// <summary>
        /// 记录文字信息
        /// </summary>
        public void LogText(params string[] warningSs)
        {
            WriteLog("信息", warningSs);
        }

        /// <summary>
        /// 日志记录文件夹(默认"C:\Logs\")
        /// </summary>
        public string FileFolder
        {
            get
            {
                //默认位置
                if (string.IsNullOrEmpty(_fileFolder))
                {
                    //_fileFolder = @"C:\Logs\";
                    _fileFolder = string.Format("{0}", AppDomain.CurrentDomain.BaseDirectory).TrimEnd('\\') + "\\Logs\\";
                }
                return _fileFolder;
            }
            set { _fileFolder = value; }
        }
        private string _fileFolder = string.Empty;

        /// <summary>
        /// 日志记录文件名(默认格式:"yyyyMMdd.log",即一天生成一个文件)
        /// </summary>
        public string FileName
        {
            get
            {
                //默认名称,按年月日
                if (string.IsNullOrEmpty(_fileName))
                {
                    RefreshFileNameByDate();//按当前日期,刷新日志文件名
                }

                //tzxtodo:机器启动后跨日期运行,则文件名不准确,只能说明它是在那天首次写日志,而非全是那天的日志
                return _fileName;
            }
            set { _fileName = value; }
        }
        private string _fileName = "";

        /// <summary>
        /// 按当前日期,刷新日志文件名
        /// </summary>
        private void RefreshFileNameByDate()
        {
            _fileName = string.Format("{0}.log", DateTime.Today.ToString("yyyyMMdd"));
        }

        /// <summary>
        /// 将信息写入到日志文本文件中
        /// </summary>
        /// <param name="logType">日志类型</param>
        /// <param name="logs">记录信息</param>
        private void WriteLog(string logType, params string[] logs)
        {
            if (string.IsNullOrEmpty(logType) && (logs == null || logs.Length < 1))
            {
                return;
            }

            try
            {
                //若不是详细指定文件名,则按当前日期,刷新日志文件名
                if (!isNamedLogFile)
                {
                    RefreshFileNameByDate();//按当前日期,刷新日志文件名
                }

                FileInfo info = new FileInfo(FileFolder.TrimEnd('\\') + '\\' + FileName.TrimStart('\\'));

                if (info.Directory != null)
                {
                    if (!info.Directory.Exists)
                    {
                        info.Directory.Create();
                    }
                }

                lock (this)
                {
                    using (StreamWriter writer = File.AppendText(info.FullName))
                    {
                        writer.Write("{0}\t", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); //记录时间
                        writer.Write("{0}\t", logType); //记录类型

                        int logLength = logs.Length;
                        for (int i = 0; i < logLength; i++)
                        {
                            writer.Write(logs[i]); //记录消息
                            if (i <= logLength - 1 - 1)
                            {
                                writer.Write("\t");
                            }
                        }

                        writer.Write(Environment.NewLine);
                        writer.Flush();
                        writer.Close();
                    }
                }
            }
            catch
            {
                //写文件失败
                throw; //do something
            }
        }

    }

    #region test
    ///// <summary>
    ///// 测试Demo
    ///// </summary>
    //internal class TestLogFile
    //{
    //    private void Test()
    //    {
    //        LogFile lf = LogFile.Instance(@"C:\LOGS\", "aaaa.log");

    //        ApplicationException appEx = new ApplicationException("瞎搞出来的错误!");
    //        lf.LogException(appEx);

    //        //lf.Xml_Path = "mylog.log";
    //        lf.LogText("aaa", "bbb", "ccc", "ddd", "deeee");

    //        //////////////////////////////////////////////////////////////////////////////
    //        LogFile lf2 = LogFile.Instance();

    //        ApplicationException appEx2 = new ApplicationException("瞎搞出来的错误2!");
    //        lf2.LogException(appEx2);

    //        //lf.Xml_Path = "mylog.log";
    //        lf2.LogText("aaa2", "bbb2", "c2cc", "d2dd", "dee2ee");

    //        try
    //        {
    //            int i = 0;
    //            int j = 9;
    //            int k = j - i - 9;

    //            System.Diagnostics.Debug.WriteLine(j/k);
    //        }
    //        catch (Exception e)
    //        {
    //            LogFile.Instance().LogException(e);
    //        }
    //    }
    //}
    #endregion

}